home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i053: FBM, image manipulation library, Part07/08
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Michael.Mauldin@NL.CS.CMU.EDU
- Posting-number: Volume 19, Issue 53
- Archive-name: fbm/part07
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 7 (of 8)."
- # Contents: fbham.c flgifr.c fliff.c
- # Wrapped by rsalz@fig.bbn.com on Fri Jun 9 08:38:29 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'fbham.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'fbham.c'\"
- else
- echo shar: Extracting \"'fbham.c'\" \(14765 characters\)
- sed "s/^X//" >'fbham.c' <<'END_OF_FILE'
- X/*****************************************************************
- X * fbham.c: FBM Library 0.94 (Beta test) 20-May-89 Michael Mauldin
- X *
- X * fbham.c: Write a 24bit RGB file as an Amiga HAM IFF file
- X *
- X * USAGE
- X * % fbham < image1 > image2
- X *
- X * EDITLOG
- X * LastEditDate = Sat May 20 19:15:08 1989 - Michael Mauldin
- X * LastFileName = /usr2/mlm/src/misc/fbm/fbham.c
- X *
- X * HISTORY
- X * 20-May-89 Michael Mauldin (mlm) at Carnegie Mellon University
- X * Beta release (version 0.94) mlm@cs.cmu.edu
- X *
- X * 20-Apr-89 C. Harald Koch (chk) at DCIEM Toronto.
- X * Created. chk@ben.dciem.dnd.ca
- X *
- X *================================================================
- X * based on ray2.c from DBW_Render, Copyright 1987 David B. Wecker
- X *
- X * From: chk@dretor.dciem.dnd.ca (C. Harald Koch)
- X * Subject: fbham.c - convert a 24bit FBM file to an IFF file using HAM mode
- X * To: Michael.Mauldin@nl.cs.cmu.edu (Michael Maudlin)
- X * Date: Mon, 1 May 89 17:21:16 EDT
- X * X-Mailer: ELM [version 2.2 PL0]
- X *
- X * This is the source to my program to convert from a 24bit FBM file to Amiga
- X * HAM mode. It is based on Dave Wecker's RAY2 program, which converts the
- X * output of his raytracer to HAM mode. His code uses the Amiga graphics
- X * library to plot the pixels in a framebuffer for encoding; this version will
- X * run standalone.
- X *
- X * There may be bugs, although it works well for me here. It is probably not in
- X * the format you want for FBM source; Please go ahead and modify it. There is
- X * probably room for some command line options for various things (such as the
- X * verbose output, run length encoding, etc) which I haven't needed and so
- X * haven't added.
- X *
- X * I will send you the IRIS programs when I get them. Enjoy!
- X * -chk
- X *****************************************************************/
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "fbm.h"
- X
- X# define USAGE "Usage: fbham < image > image"
- X
- X#ifndef lint
- Xstatic char *fbmid =
- X"$FBM fbham.c <0.93> 03-May-89 (C) 1989 by C. Harald Koch$";
- X#endif
- X
- X#define DEPTH 6 /* max depth of Amiga HAM image */
- X
- X#define BMHDsize 20L /* chunk sizes */
- X#define CMAPsize 96L
- X#define CAMGsize 4L
- X#define BODYsize ((long)(16000L))
- X#define FORMsize (BODYsize+CAMGsize+CMAPsize+BMHDsize+36L)
- X
- Xunsigned char *planes[DEPTH]; /* bitplane pointers */
- X
- Xstatic int comp = 1; /* compress image? */
- Xstatic int depth = DEPTH; /* depth of image being created */
- Xstatic int colors = 16; /* number of colors in color lookup table */
- Xstatic int colorstats[4096][2]; /* color usage statistics */
- Xstatic int row_size; /* number of bytes in IFF row of data */
- X
- X/* temp variables for writing IFF file */
- Xchar str[40];
- Xlong lng, pos1, pos2;
- Xshort wrd;
- Xunsigned char byt;
- Xunsigned char *dest, destbuf[BUFSIZ];
- X
- X
- Xmain(argc, argv)
- Xchar *argv[];
- X{
- X FBM input;
- X
- X /* Clear the memory pointers so alloc_fbm won't be confused */
- X input.cm = input.bm = (unsigned char *) NULL;
- X
- X /* Read the image and rotate it */
- X if (!read_bitmap(&input, argc > 0 ? argv[1] : (char *) NULL))
- X {
- X exit(1);
- X }
- X
- X /* slight sanity checks. could be better. */
- X if (input.hdr.physbits != 8 || input.hdr.planes != 3) {
- X fprintf(stderr, "input file must be 24 bit RGB data\n");
- X exit(1);
- X }
- X
- X /* convert to HAM */
- X if (!fbm2ham(&input, stdout)) {
- X exit(1);
- X }
- X
- X exit(0);
- X}
- X
- X
- X/************************ run length encoding from Amiga RKM *****************/
- X#define DUMP 0 /* list of different bytes */
- X#define RUN 1 /* single run of bytes */
- X#define MinRun 3 /* shortest allowed run */
- X#define MaxRun 128 /* longest run (length is signed char) */
- X#define MaxDat 128 /* longest block of unencoded data */
- X#define GetByte() (*source++)
- X#define PutByte(c) { *dest++ = (c); ++PutSize; }
- X#define OutDump(nn) dest = PutDump(dest,nn);
- X#define OutRun(nn,cc) dest = PutRun(dest,nn,cc);
- X
- Xint PutSize;
- Xchar buf[256];
- X
- Xunsigned char *
- XPutDump(dest, nn)
- Xunsigned char *dest;
- Xint nn;
- X{
- X int i;
- X
- X PutByte(nn - 1);
- X for (i = 0; i < nn; i++)
- X PutByte(buf[i]);
- X return (dest);
- X}
- X
- Xunsigned char *
- XPutRun(dest, nn, cc)
- Xunsigned char *dest;
- Xint nn, cc;
- X{
- X PutByte(-(nn - 1));
- X PutByte(cc);
- X return (dest);
- X}
- X
- X/* PackRow - pack a row of data using Amiga IFF RLE */
- Xint
- XPackRow(pSource, pDest, RowSize)
- Xunsigned char **pSource, **pDest;
- Xint RowSize;
- X{
- X unsigned char *source, *dest;
- X char c, lastc = '\000';
- X int mode = DUMP, nbuf = 0, /* number of chars in buf */
- X rstart = 0; /* buf index current run starts */
- X
- X source = *pSource;
- X dest = *pDest;
- X
- X PutSize = 0;
- X buf[0] = lastc = c = GetByte();
- X nbuf = 1;
- X RowSize--;
- X
- X for (; RowSize; --RowSize) {
- X buf[nbuf++] = c = GetByte();
- X
- X switch (mode) {
- X case DUMP:
- X if (nbuf > MaxDat) {
- X OutDump(nbuf - 1);
- X buf[0] = c;
- X nbuf = 1;
- X rstart = 0;
- X break;
- X }
- X if (c == lastc) {
- X if (nbuf - rstart >= MinRun) {
- X if (rstart > 0)
- X OutDump(rstart);
- X mode = RUN;
- X }
- X else if (rstart == 0)
- X mode = RUN;
- X }
- X else
- X rstart = nbuf - 1;
- X break;
- X
- X case RUN:
- X if ((c != lastc) || (nbuf - rstart > MaxRun)) {
- X OutRun((nbuf - 1) - rstart, lastc);
- X buf[0] = c;
- X nbuf = 1;
- X rstart = 0;
- X mode = DUMP;
- X }
- X break;
- X }
- X lastc = c;
- X }
- X switch (mode) {
- X case DUMP:
- X OutDump(nbuf);
- X break;
- X case RUN:
- X OutRun(nbuf - rstart, lastc);
- X break;
- X }
- X
- X *pSource = source;
- X *pDest = dest;
- X
- X return (PutSize);
- X}
- X/******************* end of RKM RL encoding routines **********************/
- X
- X
- X/* build_histogram - count frequency of 12bit colors in an FBM image */
- Xbuild_histogram(image)
- XFBM *image;
- X{
- X int i, j, t0, t1, gap, val, used;
- X unsigned char *rp, *gp, *bp;
- X int diff;
- X
- X /* initialize color statistics. */
- X for (i = 0; i < 4096; i++) {
- X colorstats[i][0] = i;
- X colorstats[i][1] = 0;
- X }
- X
- X /* obtain pointers to the beginning of each plane (Red, Green, Blue) */
- X rp = image->bm;
- X gp = rp + image->hdr.plnlen;
- X bp = gp + image->hdr.plnlen;
- X
- X /* count the number of occurences of each color in the image */
- X for (i = 0 ; i < image->hdr.plnlen ; i++) {
- X val = ((*rp++ & 0xf0) << 4) + (*gp++ & 0xf0) + ((*bp++ & 0xf0) >> 4);
- X val %= 4096;
- X if (colorstats[val][1] < 32767) {
- X colorstats[val][1]++;
- X }
- X }
- X
- X /* sort the color stats in order of decreasing usage */
- X for (gap = 2048; gap > 0; gap /= 2) {
- X for (i = gap; i < 4096; i++) {
- X for (j = i - gap; j >= 0 &&
- X colorstats[j][1] < colorstats[j + gap][1]; j -= gap) {
- X t0 = colorstats[j][0];
- X t1 = colorstats[j][1];
- X colorstats[j][0] = colorstats[j + gap][0];
- X colorstats[j][1] = colorstats[j + gap][1];
- X colorstats[j + gap][0] = t0;
- X colorstats[j + gap][1] = t1;
- X }
- X }
- X }
- X
- X /* count the number of colors actually used in the image */
- X for (used = 0; used < 4096 && colorstats[used][1] > 0; used++);
- X fprintf(stderr, "Used %d colors out of a possible 4096\n", used);
- X}
- X
- X/*-
- X * plot_pixel - plot a color in an Amiga style bitmap (one plane per bit)
- X *
- X * Description:
- X * A somewhat optimized routine to set/reset one bit in each plane
- X * at the specified (x,y) coordinates. plane i gets the bit in
- X * position i of color. a replacement for the Amiga WritePixel call.
- X-*/
- Xplot_pixel(planes, x, y, color)
- Xunsigned char *planes[];
- Xint x, y;
- Xregister int color;
- X{
- X register int bit;
- X register unsigned char shifted_bit = 1 << (7-(x%8));
- X register int array_offset = y * row_size + x/8;
- X register int i;
- X
- X for (i = 0; color && i < depth; i++) {
- X bit = color & 1;
- X color >>= 1;
- X
- X if (bit) *(planes[i] + array_offset) |= shifted_bit;
- X }
- X}
- X
- X
- X/*-
- X * fbm2ham - write an FBM image in HAM IFF format on the given file pointer.
- X *
- X-*/
- Xfbm2ham(image, ofil)
- XFBM *image;
- XFILE *ofil;
- X{
- X int i, j, k, gap, t0, t1, prgb, crgb, cpix, ppix, maxdis, used;
- X int c1, c2, diff;
- X unsigned char *rp, *gp, *bp;
- X
- X fprintf(stderr, "Building a color histogram:\n");
- X build_histogram(image);
- X
- X /* convert the image to an Amiga HAM bitplane based image */
- X cpix = 0;
- X crgb = colorstats[0][1];
- X
- X rp = image->bm;
- X gp = rp + image->hdr.plnlen;
- X bp = gp + image->hdr.plnlen;
- X
- X row_size = ((image->hdr.cols + 15) / 16) * 2;
- X diff = image->hdr.rowlen - image->hdr.cols;
- X
- X for (i = 0; i < depth ; i++) {
- X planes[i] = (unsigned char *)malloc(row_size * image->hdr.rows);
- X }
- X
- X for (i = 0; i < image->hdr.rows; i ++) {
- X /* verbose output because this program is slow even on a Sun */
- X if (i%50 == 0) { fprintf(stderr, "...%d", i); fflush(stderr); }
- X
- X /* step through current row, converting FBM pixel to nearest equivalent
- X * HAM pixel */
- X for (j = 0; j < image->hdr.cols; j++) {
- X prgb = crgb;
- X crgb = ((*rp++ & 0xf0) << 4) + (*gp++ & 0xf0) + ((*bp++ & 0xf0) >> 4);
- X crgb %= 4096;
- X ppix = cpix;
- X
- X /* start of scan line is ALWAYS an absolute color */
- X if (j == 0)
- X cpix = getcolor(ppix, &crgb, -1);
- X else
- X cpix = getcolor(ppix, &crgb, prgb);
- X
- X /* plot the computed pixel */
- X plot_pixel(planes, j, i, cpix);
- X }
- X rp += diff;
- X gp += diff;
- X bp += diff;
- X }
- X fprintf(stderr, "\n");
- X
- X /* Now we write the planes[] array we just created in ILBM format */
- X sprintf(str, "FORM");
- X fwrite(str, 1, 4, ofil);
- X pos1 = ftell(ofil);
- X lng = FORMsize;
- X fwrite(&lng, 4, 1, ofil);
- X sprintf(str, "ILBM");
- X fwrite(str, 1, 4, ofil);
- X
- X sprintf(str, "BMHD");
- X fwrite(str, 1, 4, ofil);
- X lng = BMHDsize;
- X fwrite(&lng, 4, 1, ofil);
- X wrd = image->hdr.cols;
- X fwrite(&wrd, 2, 1, ofil); /* width */
- X wrd = image->hdr.rows;
- X fwrite(&wrd, 2, 1, ofil); /* height */
- X wrd = 0;
- X fwrite(&wrd, 2, 1, ofil); /* top */
- X wrd = 0;
- X fwrite(&wrd, 2, 1, ofil); /* left */
- X byt = depth;
- X fwrite(&byt, 1, 1, ofil); /* Depth */
- X byt = 0;
- X fwrite(&byt, 1, 1, ofil); /* mask */
- X byt = comp;
- X fwrite(&byt, 1, 1, ofil); /* compress */
- X byt = 0;
- X fwrite(&byt, 1, 1, ofil); /* pad */
- X wrd = 0;
- X fwrite(&wrd, 2, 1, ofil); /* transparency */
- X byt = 10;
- X fwrite(&byt, 1, 1, ofil); /* aspect x */
- X byt = 11;
- X fwrite(&byt, 1, 1, ofil); /* aspect y */
- X wrd = image->hdr.cols;
- X fwrite(&wrd, 2, 1, ofil); /* page width */
- X wrd = image->hdr.rows;
- X fwrite(&wrd, 2, 1, ofil); /* page height */
- X
- X /* CAMG chunk for displaying files on the Amiga. should include at least
- X * the HAM flag; I also add lace if the picture is large enough. Perhaps
- X * this should be an option. -CHK */
- X sprintf(str, "CAMG");
- X fwrite(str, 1, 4, ofil);
- X lng = CAMGsize;
- X fwrite(&lng, 4, 1, ofil);
- X if (image->hdr.rows > 200)
- X lng = 0x804L; /* HAM | LACE */
- X else
- X lng = 0x800L; /* HAM */
- X fwrite(&lng, 4, 1, ofil);
- X
- X /* write out the color lookup table */
- X sprintf(str, "CMAP");
- X fwrite(str, 1, 4, ofil);
- X lng = CMAPsize;
- X fwrite(&lng, 4, 1, ofil);
- X for (i = 0; i < 32; i++) {
- X str[0] = (colorstats[i][0] >> 4) & 0xF0;
- X str[1] = (colorstats[i][0]) & 0xF0;
- X str[2] = (colorstats[i][0] << 4) & 0xF0;
- X fwrite(str, 1, 3, ofil);
- X }
- X
- X sprintf(str, "BODY");
- X fwrite(str, 1, 4, ofil);
- X pos2 = ftell(ofil);
- X lng = BODYsize;
- X fwrite(&lng, 4, 1, ofil);
- X
- X lng = 0L;
- X
- X for (i = 0; i < image->hdr.rows; i ++) {
- X for (j = 0; j < depth; j++) {
- X if (comp) {
- X dest = destbuf;
- X wrd = PackRow(&planes[j], &dest, row_size);
- X lng += (long) wrd;
- X fwrite(destbuf, 1, wrd, ofil);
- X }
- X else {
- X fwrite(planes[j], 1, row_size, ofil);
- X planes[j] += row_size;
- X }
- X }
- X }
- X if (comp) {
- X fseek(ofil, (long) pos2, 0);
- X fwrite(&lng, 4, 1, ofil);
- X lng -= BODYsize;
- X lng += FORMsize;
- X fseek(ofil, (long) pos1, 0);
- X fwrite(&lng, 4, 1, ofil);
- X }
- X
- X return 1;
- X}
- X
- X/* get the next encoding for a pixel, based on the previous pixel and the
- X * current 12 bit RGB value */
- X
- X#define BPP 4 /* Bits per pixel */
- X#define MAXGRAY (1 << BPP)
- X#define ABS(x) ((x) < 0 ? -(x) : (x))
- X
- X/*-
- X * first, check to see if pixel is the same color. if so, return
- X * check if only one of R, G, B have changed. if so, return new pixel.
- X * find closest entry in colormap. if exact match, return it.
- X * modify one of R, G, B (whichever difference is largest)
- X * compare previous calculation to best match in color table. return
- X * whichever is a better match.
- X-*/
- Xgetcolor(ppix, crgb, prgb)
- Xint ppix, *crgb, prgb;
- X{
- X int i, j, val, cr, cg, cb, pr, pg, pb, nr, ng, nb, best, dist, nrgb;
- X
- X /* if same color, then do a NOOP (same as previous pixel) */
- X if (*crgb == prgb)
- X return (ppix);
- X
- X /* set up for comparisons */
- X cb = *crgb & (MAXGRAY - 1);
- X cg = (*crgb >> BPP) & (MAXGRAY - 1);
- X cr = (*crgb >> (BPP * 2)) & (MAXGRAY - 1);
- X
- X pb = prgb & (MAXGRAY - 1);
- X pg = (prgb >> BPP) & (MAXGRAY - 1);
- X pr = (prgb >> (BPP * 2)) & (MAXGRAY - 1);
- X
- X /* see if only one plane changed, if so, use HAM encoding */
- X if (prgb != -1) {
- X if (pr == cr && pg == cg)
- X return (cb + 0x10);
- X if (pr == cr && pb == cb)
- X return (cg + 0x30);
- X if (pg == cg && pb == cb)
- X return (cr + 0x20);
- X }
- X
- X /* else look for an exact match in the color table (or minimal distance) */
- X for (i = 0; i < colors; i++) {
- X if (colorstats[i][0] == *crgb)
- X return (i);
- X if (i == 0) {
- X best = 0;
- X dist = distance(colorstats[i][0], *crgb);
- X }
- X else if ((j = distance(colorstats[i][0], *crgb)) < dist) {
- X best = i;
- X dist = j;
- X }
- X }
- X
- X /* do a forced absolute */
- X if (prgb == -1) {
- X *crgb = colorstats[best][0];
- X return (best);
- X }
- X
- X /* find which color is off the most from previous */
- X i = 0;
- X val = ABS(cr - pr);
- X if (ABS(cg - pg) > val) {
- X i = 1;
- X val = ABS(cg - pg);
- X }
- X if (ABS(cb - pb) > val) {
- X i = 2;
- X val = ABS(cb - pb);
- X }
- X
- X nr = pr;
- X ng = pg;
- X nb = pb;
- X switch (i) {
- X case 0:
- X nr = cr;
- X val = nr + 0x20;
- X break;
- X case 1:
- X ng = cg;
- X val = ng + 0x30;
- X break;
- X case 2:
- X nb = cb;
- X val = nb + 0x10;
- X break;
- X }
- X nrgb = (nr << (2 * BPP)) + (ng << BPP) + nb;
- X
- X /* now pick the best */
- X if (distance(nrgb, *crgb) < dist) {
- X
- X /* do a best relative */
- X *crgb = nrgb;
- X return (val);
- X }
- X
- X /* do a best absolute */
- X *crgb = colorstats[best][0];
- X return (best);
- X}
- X
- X/* calculate distance between two colors in 3D space */
- Xdistance(argb, brgb)
- X{
- X int b, g, r;
- X
- X /* set up for comparisons */
- X b = argb & (MAXGRAY - 1);
- X g = (argb >> BPP) & (MAXGRAY - 1);
- X r = (argb >> (BPP * 2)) & (MAXGRAY - 1);
- X
- X b -= brgb & (MAXGRAY - 1);
- X g -= (brgb >> BPP) & (MAXGRAY - 1);
- X r -= (brgb >> (BPP * 2)) & (MAXGRAY - 1);
- X
- X return (r * r + g * g + b * b);
- X}
- END_OF_FILE
- if test 14765 -ne `wc -c <'fbham.c'`; then
- echo shar: \"'fbham.c'\" unpacked with wrong size!
- fi
- # end of 'fbham.c'
- fi
- if test -f 'flgifr.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'flgifr.c'\"
- else
- echo shar: Extracting \"'flgifr.c'\" \(13672 characters\)
- sed "s/^X//" >'flgifr.c' <<'END_OF_FILE'
- X/*****************************************************************
- X * flgifr.c: FBM Library 0.91 (Beta test) 26-Apr-89 Michael Mauldin
- X *
- X * Copyright (C) 1989 by Michael Mauldin. Permission is granted to
- X * use this file in whole or in part provided that you do not sell it
- X * for profit and that this copyright notice is retained unchanged.
- X *
- X * Derived from 'giftorle', written by David Koblas
- X *
- X * +------------------------------------------------------------------+
- X * | Copyright 1989, David Koblas. |
- X * | You may copy this file in whole or in part as long as you |
- X * | don't try to make money off it, or pretend that you wrote it. |
- X * +------------------------------------------------------------------+
- X *
- X * flgifr.c:
- X *
- X * CONTENTS
- X * read_gif (image, stream, mstr, mlen)
- X *
- X * HISTORY
- X * 26-Apr-89 Michael Mauldin (mlm) at Carnegie Mellon University
- X * Beta release (version 0.91) mlm@cs.cmu.edu
- X *
- X * 19-Feb-89 Michael Mauldin (mlm) at Carnegie Mellon University
- X * Changed name to flgifr from flgif (since there is now an flgifw)
- X *
- X * 13-Feb-89 Michael Mauldin (mlm) at Carnegie Mellon University
- X * Modified from gif2rle program Copyright 1989 by David Koblas.
- X * Converted to produce FBM image format in memory.
- X *
- X *
- X *****************************************************************/
- X
- X# include <stdio.h>
- X# include "fbm.h"
- X
- X#define MAXCOLORMAPSIZE 256
- X
- X#define TRUE 1
- X#define FALSE 0
- X#define BAD 0
- X#define OK 1
- X
- X#define MAX_LWZ_BITS 12
- X
- X#define ReadOK(file,buffer,len) (fread(buffer,len,1,file)!=0)
- X#define EasyFail(str,status) while(1){fprintf(stderr,str);return(status);}
- X#define HardFail(str,status) while(1){fprintf(stderr,str);exit (status);}
- X
- X#define LM_to_uint(a,b) (((b)<<8)|(a))
- X
- X#ifndef lint
- Xstatic char *fbmid =
- X "$FBM flgifr.c <0.91> 26-Apr-89 (C) 1989 by Michael Mauldin$";
- X#endif
- X
- Xread_gif (image, fd, mstr, mlen)
- XFBM *image;
- XFILE *fd;
- Xchar *mstr;
- Xint mlen;
- X{
- X unsigned char buf[16];
- X unsigned char c;
- X int use_global_colormap;
- X int bit_pixel;
- X int count = 0;
- X int rows, cols, rowlen, depth, colors;
- X
- X /* Read magic number 'GIF87a' */
- X buf[0] = NEXTMCH (fd, mstr, mlen) & 0xff;
- X buf[1] = NEXTMCH (fd, mstr, mlen) & 0xff;
- X buf[2] = NEXTMCH (fd, mstr, mlen) & 0xff;
- X buf[3] = NEXTMCH (fd, mstr, mlen) & 0xff;
- X buf[4] = NEXTMCH (fd, mstr, mlen) & 0xff;
- X buf[5] = NEXTMCH (fd, mstr, mlen) & 0xff;
- X buf[6] = 0;
- X
- X if (strcmp (buf, GIF_MAGIC) != 0)
- X EasyFail("bad magic number (version mismatch?)\n", BAD);
- X
- X if (!ReadOK (fd, buf, 7))
- X EasyFail("error reading screen descriptor\n", BAD);
- X
- X /* Read image data */
- X image->hdr.cols = cols = LM_to_uint(buf[0], buf[1]);
- X image->hdr.rows = rows = LM_to_uint(buf[2], buf[3]);
- X image->hdr.planes = 1;
- X image->hdr.bits = depth = (buf[4] & 0x07) + 1;
- X image->hdr.physbits = 8;
- X
- X /* Pad to even byte */
- X if (depth == 1)
- X { image->hdr.rowlen = rowlen = 16 * ((cols + 15) / 16); }
- X else
- X { image->hdr.rowlen = rowlen = 2 * ((cols + 1) / 2); }
- X
- X image->hdr.plnlen = rowlen * rows;
- X colors = 1 << depth;
- X image->hdr.clrlen = 3 * colors;
- X image->hdr.title[0] = '\0';
- X image->hdr.credits[0] = '\0';
- X
- X /* Try to guess aspect ratio */
- X if (cols == 320 && rows == 200) { image->hdr.aspect = 1.2; }
- X else if (cols == 320 && rows == 175) { image->hdr.aspect = 1.2; }
- X else if (cols == 320 && rows == 400) { image->hdr.aspect = 0.6; }
- X else if (cols == 320 && rows == 350) { image->hdr.aspect = 0.6; }
- X else if (cols == 640 && rows == 200) { image->hdr.aspect = 2.4; }
- X else if (cols == 640 && rows == 175) { image->hdr.aspect = 2.4; }
- X else if (cols == 640 && rows == 400) { image->hdr.aspect = 1.2; }
- X else if (cols == 640 && rows == 350) { image->hdr.aspect = 1.2; }
- X else { image->hdr.aspect = 1.0; }
- X
- X# ifdef DEBUG
- X fprintf (stderr, "\nImage file header:\n\n");
- X fprintf (stderr, "cols %d\n", image->hdr.cols);
- X fprintf (stderr, "rows %d\n", image->hdr.rows);
- X fprintf (stderr, "planes %d\n", image->hdr.planes);
- X fprintf (stderr, "bits %d\n", image->hdr.bits);
- X fprintf (stderr, "physbits %d\n", image->hdr.physbits);
- X fprintf (stderr, "rowlen %d\n", image->hdr.rowlen);
- X fprintf (stderr, "plnlen %d\n", image->hdr.plnlen);
- X fprintf (stderr, "clrlen %d\n", image->hdr.clrlen);
- X fprintf (stderr, "aspect %1.3lf\n", image->hdr.aspect);
- X fprintf (stderr, "title '%s'\n", image->hdr.title);
- X fprintf (stderr, "credits '%s'\n", image->hdr.credits);
- X# endif
- X
- X /* Allocate image */
- X alloc_fbm (image);
- X
- X /* Read colormap if given */
- X if ((buf[4] & 0x80) == 0x80)
- X { if (ReadColorMap (fd, colors, image->cm) == BAD)
- X return (BAD);
- X }
- X
- X while (1)
- X { if (!ReadOK (fd, &c, 1))
- X EasyFail("No image data -- EOF\n", BAD);
- X
- X if (c == ';')
- X return OK;
- X
- X if (c == '!')
- X { if (!ReadOK (fd, &c, 1))
- X EasyFail("No extention function code -- EOF\n", BAD);
- X if (IgnoreExtention(fd) == BAD)
- X return (BAD);
- X }
- X
- X if (c != ',')
- X { fprintf(stderr, "Bogus character ignoring '%c'\n", c);
- X continue;
- X }
- X
- X if (count == 1)
- X HardFail("This file contains more than one image! FAILING\n", 1);
- X count++;
- X
- X if (!ReadOK (fd, buf, 9))
- X EasyFail("Couldn't read left/top/width/height\n", TRUE);
- X
- X# ifdef DEBUG
- X fprintf (stderr, "Image description: ");
- X for (i=0; i<9; i++) fprintf (stderr, "%02x", buf[i]);
- X fprintf (stderr, "\n");
- X# endif
- X
- X if ((buf[8] & 0x80) == 0x80)
- X use_global_colormap = FALSE;
- X else
- X use_global_colormap = TRUE;
- X
- X bit_pixel = 2 << (buf[8] & 0x07);
- X
- X if (!use_global_colormap && bit_pixel > colors)
- X { HardFail ("Local colormap has more colors than global!\n", BAD); }
- X
- X if (!use_global_colormap)
- X { fprintf (stderr,
- X "Overriding global colormap (%d) with local (%d)\n",
- X colors, bit_pixel);
- X
- X colors = bit_pixel;
- X image->hdr.clrlen = 3 * colors;
- X
- X if (ReadColorMap(fd, colors, image->cm) == BAD)
- X return BAD;
- X }
- X
- X fprintf (stderr, "Reading GIF image [%dx%d], %d bits",
- X image->hdr.cols, image->hdr.rows, image->hdr.bits);
- X if (image->hdr.clrlen > 0)
- X { fprintf (stderr, ", %d colors", image->hdr.clrlen / 3); }
- X else if (image->hdr.bits > 1)
- X { fprintf (stderr, ", grayscale"); }
- X
- X if ((buf[8] & 0x40) == 0x40)
- X { fprintf (stderr, ", interlaced"); }
- X fprintf (stderr, "\n");
- X
- X
- X if ((buf[8] & 0x40) == 0x40)
- X {
- X if (ReadInterlaced(fd,
- X LM_to_uint(buf[4],buf[5]),
- X LM_to_uint(buf[6],buf[7]),
- X image->bm,
- X rowlen) == BAD)
- X return BAD;
- X }
- X else
- X { if (ReadRaster(fd,
- X LM_to_uint(buf[4], buf[5]),
- X LM_to_uint(buf[6], buf[7]),
- X image->bm,
- X rowlen) == BAD)
- X return BAD;
- X else
- X return OK;
- X }
- X }
- X}
- X
- XReadColorMap (fd, number, buffer)
- X FILE *fd;
- X int number;
- X unsigned char *buffer;
- X{
- X int i;
- X unsigned char rgb[3], *red, *grn, *blu;
- X
- X red = buffer;
- X grn = buffer + number;
- X blu = grn + number;
- X
- X for (i = 0; i < number; i++)
- X { if (!ReadOK (fd, rgb, sizeof(rgb)))
- X EasyFail("Bogus colormap\n", BAD);
- X
- X red[i] = rgb[0];
- X grn[i] = rgb[1];
- X blu[i] = rgb[2];
- X }
- X
- X return OK;
- X}
- X
- XIgnoreExtention(fd)
- X FILE *fd;
- X{
- X static char buf[256];
- X unsigned char c;
- X
- X while (1)
- X {
- X if (!ReadOK (fd, &c, 1))
- X EasyFail("EOF in extention\n", BAD);
- X
- X if (c == 0)
- X return OK;
- X
- X if (read(fd, buf, (int) c) != (int) c)
- X EasyFail("EOF in extention\n", BAD);
- X }
- X}
- X
- XGetCode(fd, code_size, flag)
- X FILE *fd;
- X int code_size;
- X int flag;
- X{
- X static unsigned char buf[280];
- X static int curbit, lastbit, done, last_byte;
- X int i, j, ret;
- X unsigned char count;
- X
- X if (flag)
- X {
- X curbit = 0;
- X lastbit = 0;
- X done = FALSE;
- X return 0;
- X }
- X
- X if ((curbit + code_size) >= lastbit)
- X { if (done)
- X { if (curbit >= lastbit)
- X EasyFail("Ran off the end of my bits\n", -1);
- X }
- X buf[0] = buf[last_byte - 2];
- X buf[1] = buf[last_byte - 1];
- X
- X if (!ReadOK (fd, &count, 1))
- X { EasyFail("Error in getting buffer size\n", -1); }
- X
- X if (count == 0)
- X { done = TRUE; }
- X
- X else if (!ReadOK (fd, &buf[2], count))
- X EasyFail("Error in getting buffer\n", -1);
- X
- X last_byte = 2 + count;
- X curbit = (curbit - lastbit) + 16;
- X lastbit = (2 + count) * 8;
- X }
- X
- X ret = 0;
- X
- X for (i = curbit, j = 0; j < code_size; i++, j++)
- X ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
- X
- X curbit += code_size;
- X
- X return ret;
- X}
- X
- XLWZReadByte(fd, flag, input_code_size)
- X FILE *fd;
- X int flag;
- X int input_code_size;
- X{
- X static int fresh = FALSE;
- X int code, incode;
- X static int code_size, set_code_size;
- X static int max_code, max_code_size;
- X static int firstcode, oldcode;
- X static int clear_code, end_code;
- X static int table[2][(1 << MAX_LWZ_BITS)];
- X static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
- X register int i;
- X
- X if (flag)
- X {
- X set_code_size = input_code_size;
- X code_size = set_code_size + 1;
- X clear_code = 1 << set_code_size;
- X end_code = clear_code + 1;
- X max_code_size = 2 * clear_code;
- X max_code = clear_code + 2;
- X
- X GetCode(fd, NULL, NULL);
- X
- X fresh = TRUE;
- X
- X for (i = 0; i < clear_code; i++)
- X {
- X table[0][i] = 0;
- X table[1][i] = i;
- X }
- X
- X for (; i < (1 << MAX_LWZ_BITS); i++)
- X table[0][i] = table[1][0] = 0;
- X
- X sp = stack;
- X return 0;
- X }
- X else if (fresh)
- X { fresh = FALSE;
- X do
- X { firstcode = oldcode =
- X GetCode(fd, code_size, FALSE);
- X } while (firstcode == clear_code);
- X
- X return firstcode;
- X }
- X
- X if (sp > stack)
- X return *--sp;
- X
- X while ((code = GetCode(fd, code_size, FALSE)) >= 0)
- X { if (code == clear_code)
- X { for (i = 0; i < clear_code; i++)
- X {table[0][i] = 0;
- X table[1][i] = i;
- X }
- X
- X for (; i < (1 << MAX_LWZ_BITS); i++)
- X table[0][i] = table[1][i] = 0;
- X
- X code_size = set_code_size + 1;
- X max_code_size = 2 * clear_code;
- X max_code = clear_code + 2;
- X sp = stack;
- X firstcode = oldcode =
- X GetCode(fd, code_size, FALSE);
- X return firstcode;
- X }
- X else if (code == end_code)
- X { unsigned char count;
- X unsigned char junk;
- X
- X while (ReadOK (fd, &count, 1) && (count != 0))
- X while (count-- != 0 && ReadOK (fd, &junk, 1));
- X
- X if (count != 0)
- X EasyFail("missing EOD in data stream (common occurance)\n", -3);
- X
- X return -2;
- X }
- X
- X incode = code;
- X
- X if (code >= max_code)
- X { *sp++ = firstcode;
- X code = oldcode;
- X }
- X
- X while (code >= clear_code)
- X {
- X *sp++ = table[1][code];
- X if (code == table[0][code])
- X EasyFail("Circular table entry BIG ERROR\n", -1);
- X code = table[0][code];
- X }
- X
- X *sp++ = firstcode = table[1][code];
- X
- X if ((code = max_code) < (1 << MAX_LWZ_BITS))
- X {
- X table[0][code] = oldcode;
- X table[1][code] = firstcode;
- X max_code++;
- X
- X if ((max_code >= max_code_size) &&
- X (max_code_size < (1 << MAX_LWZ_BITS)))
- X {
- X max_code_size *= 2;
- X code_size++;
- X }
- X }
- X oldcode = incode;
- X
- X if (sp > stack)
- X return *--sp;
- X }
- X
- X return code;
- X}
- X
- XReadInterlaced(fd, len, height, buffer, rowlen)
- X FILE *fd;
- X int len, height;
- X unsigned char *buffer;
- X int rowlen;
- X{
- X unsigned char c;
- X register unsigned char *bmp;
- X register int v;
- X register int xpos = 0;
- X register int ypos = 0, pass = 0;
- X register int maxypos = 0;
- X
- X
- X if (!ReadOK(fd, &c, 1))
- X EasyFail("Bogus image data -- EOF\n", BAD);
- X if (LWZReadByte(fd, TRUE, c) < 0)
- X return BAD;
- X
- X while ((v = LWZReadByte(fd, FALSE, c)) >= 0)
- X {
- X if (xpos == 0)
- X { bmp = &(buffer[ypos * rowlen]);
- X if (ypos > height)
- X { fprintf (stderr, "Wanring Too much data, started to read line %d\n",
- X ypos);
- X return (OK);
- X }
- X }
- X
- X *bmp++ = v;
- X
- X if (++xpos == len)
- X {
- X xpos = 0;
- X switch (pass)
- X {
- X case 0: case 1: ypos += 8; break;
- X case 2: ypos += 4; break;
- X case 3: ypos += 2; break;
- X }
- X
- X if (ypos > maxypos) maxypos = ypos;
- X
- X if (ypos >= height)
- X {
- X switch (++pass)
- X {
- X case 1: ypos = 4; break;
- X case 2: ypos = 2; break;
- X case 3: ypos = 1; break;
- X }
- X }
- X }
- X }
- X
- X if (maxypos >= height) return OK;
- X
- X if (v == (-2))
- X return OK;
- X return BAD;
- X}
- X
- XReadRaster (fd, len, height, buffer, rowlen)
- X FILE *fd;
- X int len, height;
- X unsigned char *buffer;
- X int rowlen;
- X{
- X unsigned char c;
- X register unsigned char *bmp;
- X register int v;
- X register int xpos = 0;
- X register int ypos = 0;
- X
- X if (!ReadOK (fd, &c, 1))
- X EasyFail("Bogus image data -- EOF\n", TRUE);
- X
- X if (LWZReadByte(fd, TRUE, c) < 0)
- X return BAD;
- X
- X /* Read the raster data and dump it into the FBM bitmap */
- X while ((v = LWZReadByte(fd, FALSE, c)) >= 0)
- X {
- X if (xpos == 0)
- X { bmp = &(buffer[ypos++ * rowlen]);
- X if (ypos > height)
- X { fprintf (stderr, "Warning: too much data, started to read line %d\n",
- X ypos);
- X return (OK);
- X }
- X }
- X
- X *bmp++ = v;
- X
- X if (++xpos == len)
- X
- X if (xpos == len) xpos = 0;
- X }
- X
- X fprintf (stderr, "Done storing bitmap, xpos %d, ypos %d [%dx%d]\n",
- X xpos, ypos, len, height);
- X
- X if (ypos >= height) return OK;
- X
- X if (v == (-2))
- X return OK;
- X return BAD;
- X}
- END_OF_FILE
- if test 13672 -ne `wc -c <'flgifr.c'`; then
- echo shar: \"'flgifr.c'\" unpacked with wrong size!
- fi
- # end of 'flgifr.c'
- fi
- if test -f 'fliff.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'fliff.c'\"
- else
- echo shar: Extracting \"'fliff.c'\" \(23454 characters\)
- sed "s/^X//" >'fliff.c' <<'END_OF_FILE'
- X/*****************************************************************
- X * fliff.c: FBM Library 0.9 (Beta test) 07-Mar-89 Michael Mauldin
- X *
- X * Copyright (C) 1989 by Michael Mauldin. Permission is granted to
- X * use this file in whole or in part provided that you do not sell it
- X * for profit and that this copyright notice is retained unchanged.
- X *
- X * fliff.c:
- X *
- X * CONTENTS
- X * write_iff (image, stream)
- X * read_iff (image, stream, mstr, mlen)
- X *
- X * EDITLOG
- X * LastEditDate = Mon Mar 20 18:54:08 1989 - Michael Mauldin
- X * LastFileName = /usr2/mlm/src/misc/fbm/fliff.c
- X *
- X * HISTORY
- X * 07-Mar-89 Michael Mauldin (mlm) at Carnegie Mellon University
- X * Beta release (version 0.9) mlm@cs.cmu.edu
- X *
- X * 04-Mar-89 Michael Mauldin (mlm) at Carnegie Mellon University
- X * Read and Write support for Amiga IFF (except HAM mode)
- X *****************************************************************/
- X
- X# include <stdio.h>
- X# include <math.h>
- X# include <ctype.h>
- X# include "fbm.h"
- X
- X#ifndef lint
- Xstatic char *fbmid =
- X "$FBM fliff.c <0.9> 07-Mar-89 (C) 1989 by Michael Mauldin$";
- X#endif
- X
- X/****************************************************************
- X * from iff.h
- X ****************************************************************/
- X
- X# define BOOL int /* 1 bit value */
- X# define SBYTE char /* 8 bits signend */
- X# define UBYTE unsigned char /* 8 bits unsigned */
- X# define WORD short /* 16 bits signed */
- X# define UWORD unsigned short /* 16 bits unsigned */
- X# define LONG long /* 32 bits signed */
- X# define ID long
- X# define MakeID(a,b,c,d) ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) )
- X# define FORM MakeID('F','O','R','M')
- X# define PROP MakeID('P','R','O','P')
- X# define LIST MakeID('L','I','S','T')
- X# define CAT MakeID('C','A','T',' ')
- X# define FILLER MakeID(' ',' ',' ',' ')
- X# define NULL_CHUNK 0L /* No current chunk.*/
- X# define TRUE 1
- X# define FALSE 0
- X
- X
- X/* ---------- Chunk ----------------------------------------------------*/
- X
- X/* All chunks start with a type ID and a count of the data bytes that
- X follow--the chunk's "logical size" or "data size". If that number is odd,
- X a 0 pad byte is written, too. */
- X
- Xtypedef struct {
- X ID ckID;
- X LONG ckSize;
- X } ChunkHeader;
- X
- Xtypedef struct {
- X ID ckID;
- X LONG ckSize;
- X UBYTE ckData[ 1 /*REALLY: ckSize*/ ];
- X } Chunk;
- X
- X/*----------------------------------------------------------------------*
- X * ILBM.H Definitions for InterLeaved BitMap raster image. 1/23/86
- X *
- X * By Jerry Morrison and Steve Shaw, Electronic Arts.
- X * This software is in the public domain.
- X *
- X * This version for the Commodore-Amiga computer.
- X *----------------------------------------------------------------------*/
- X
- X# define ID_ILBM MakeID('I','L','B','M')
- X# define ID_BMHD MakeID('B','M','H','D')
- X# define ID_CMAP MakeID('C','M','A','P')
- X# define ID_GRAB MakeID('G','R','A','B')
- X# define ID_DEST MakeID('D','E','S','T')
- X# define ID_SPRT MakeID('S','P','R','T')
- X# define ID_CAMG MakeID('C','A','M','G')
- X# define ID_BODY MakeID('B','O','D','Y')
- X
- X/* ---------- BitMapHeader ---------------------------------------------*/
- X
- Xtypedef UBYTE Masking; /* Choice of masking technique.*/
- X# define mskNone 0
- X# define mskHasMask 1
- X# define mskHasTransparentColor 2
- X# define mskLasso 3
- X
- Xtypedef UBYTE Compression; /* Choice of compression algorithm applied to
- X * each row of the source and mask planes. "cmpByteRun1" is the byte run
- X * encoding generated by Mac's PackBits. See Packer.h . */
- X# define cmpNone 0
- X# define cmpByteRun1 1
- X
- X/* Aspect ratios: The proper fraction xAspect/yAspect represents the pixel
- X * aspect ratio pixel_width/pixel_height.
- X *
- X * For the 4 Amiga display modes:
- X * 320 x 200: 10/11 (these pixels are taller than they are wide)
- X * 320 x 400: 20/11
- X * 640 x 200: 5/11
- X * 640 x 400: 10/11 */
- X# define x320x200Aspect 10
- X# define y320x200Aspect 11
- X# define x320x400Aspect 20
- X# define y320x400Aspect 11
- X# define x640x200Aspect 5
- X# define y640x200Aspect 11
- X# define x640x400Aspect 10
- X# define y640x400Aspect 11
- X
- X/* A BitMapHeader is stored in a BMHD chunk. */
- Xtypedef struct {
- X UWORD w, h; /* raster width & height in pixels */
- X WORD x, y; /* position for this image */
- X UBYTE nPlanes; /* # source bitplanes */
- X Masking masking; /* masking technique */
- X Compression compression; /* compression algorithm */
- X UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
- X UWORD transparentColor; /* transparent "color number" */
- X UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
- X WORD pageWidth, pageHeight; /* source "page" size in pixels */
- X } BitMapHeader;
- X
- X/* RowBytes computes the number of bytes in a row, from the width in pixels.*/
- X# define RowBytes(w) (2 * (((w) + 15) / 16))
- X
- X
- X/* ---------- ColorRegister --------------------------------------------*/
- X/* A CMAP chunk is a packed array of ColorRegisters (3 bytes each). */
- Xtypedef struct {
- X UBYTE red, green, blue; /* MUST be UBYTEs so ">> 4" won't sign extend.*/
- X } ColorRegister;
- X
- X/* Use this constant instead of sizeof(ColorRegister). */
- X# define sizeofColorRegister 3
- X
- Xtypedef WORD Color4; /* Amiga RAM version of a color-register,
- X * with 4 bits each RGB in low 12 bits.*/
- X
- X# define swapword(X) ((((X) & 0xff) << 8) | (((X) & 0xff00) >> 8))
- X# define swaplong(X) (((unsigned) ((X) & 0xff000000) >> 24) | \
- X ((unsigned) ((X) & 0x00ff0000) >> 8) | \
- X ((unsigned) ((X) & 0x0000ff00) << 8) | \
- X ((unsigned) ((X) & 0x000000ff) << 24))
- X
- X# define swapsize(X) ((machine_byte_order () == LITTLE) ? swaplong(X) : (X))
- X
- X/* Maximum number of bitplanes in RAM. Current Amiga max w/dual playfield. */
- X# define MaxAmDepth 6
- X
- X/* Chunks must be padded to align to even boundaries */
- X# define EVENALIGN(X) (((X) + 1) & ~1)
- X
- X/* ---------- Point2D --------------------------------------------------*/
- X/* A Point2D is stored in a GRAB chunk. */
- Xtypedef struct {
- X WORD x, y; /* coordinates (pixels) */
- X } Point2D;
- X
- X/* ---------- DestMerge ------------------------------------------------*/
- X/* A DestMerge is stored in a DEST chunk. */
- Xtypedef struct {
- X UBYTE depth; /* # bitplanes in the original source */
- X UBYTE pad1; /* UNUSED; for consistency store 0 here */
- X UWORD planePick; /* how to scatter source bitplanes into destination */
- X UWORD planeOnOff; /* default bitplane data for planePick */
- X UWORD planeMask; /* selects which bitplanes to store into */
- X } DestMerge;
- X
- X/* ---------- SpritePrecedence -----------------------------------------*/
- X/* A SpritePrecedence is stored in a SPRT chunk. */
- Xtypedef UWORD SpritePrecedence;
- X
- X/* ---------- Viewport Mode --------------------------------------------*/
- X/* A Commodore Amiga ViewPort->Modes is stored in a CAMG chunk. */
- X/* The chunk's content is declared as a LONG. */
- X
- X/* ---------- CRange ---------------------------------------------------*/
- X/* A CRange is store in a CRNG chunk. */
- Xtypedef struct {
- X WORD pad1; /* reserved for future use; store 0 here */
- X WORD rate; /* color cycling rate, 16384 = 60 steps/second */
- X WORD active; /* nonzero means color cycling is turned on */
- X UBYTE low, high; /* lower and upper color registers selected */
- X } CRange;
- X
- X/*----------------------------------------------------------------------*
- X * PACKER.H typedefs for Data-Compresser. 1/22/86
- X *
- X * This module implements the run compression algorithm "cmpByteRun1"; the
- X * same encoding generated by Mac's PackBits.
- X *
- X * By Jerry Morrison and Steve Shaw, Electronic Arts.
- X * This software is in the public domain.
- X *
- X * This version for the Commodore-Amiga computer.
- X *----------------------------------------------------------------------*/
- X
- X/* This macro computes the worst case packed size of a "row" of bytes. */
- X# define MaxPackedSize(rowSize) ( (rowSize) + ( ((rowSize)+127) >> 7 ) )
- X
- X/*----------------------------------------------------------------------*
- X * unpacker.c Convert data from "cmpByteRun1" run compression. 11/15/85
- X *
- X * By Jerry Morrison and Steve Shaw, Electronic Arts.
- X * This software is in the public domain.
- X *
- X * control bytes:
- X * [0..127] : followed by n+1 bytes of data.
- X * [-1..-127] : followed by byte to be repeated (-n)+1 times.
- X * -128 : NOOP.
- X *
- X * This version for the Commodore-Amiga computer.
- X *----------------------------------------------------------------------*/
- X
- X/*----------- UnPackRow ------------------------------------------------*/
- X
- X# define UGetByte() (*source++)
- X# define UPutByte(c) (*dest++ = (c))
- X
- X/* Given POINTERS to POINTER variables, unpacks one row, updating the source
- X * and destination pointers until it produces dstBytes bytes. */
- Xstatic UnPackRow(pSource, pDest, srcBytes0, dstBytes0)
- X char **pSource, **pDest; int srcBytes0, dstBytes0; {
- X register char *source = *pSource;
- X register char *dest = *pDest;
- X register int n;
- X register char c;
- X register int srcBytes = srcBytes0, dstBytes = dstBytes0;
- X BOOL error = TRUE; /* assume error until we make it through the loop */
- X
- X
- X# ifdef DEBUG
- X fprintf (stderr, "Unpack called, src %d, dst %d\n",
- X srcBytes0, dstBytes0);
- X# endif
- X
- X while( dstBytes > 0 ) {
- X if ( (srcBytes -= 1) < 0 ) goto ErrorExit;
- X n = UGetByte() & 0x0ff;
- X
- X if (n < 128) {
- X# ifdef DEBUG
- X fprintf (stderr, "Got %02x, copying %d bytes...\n", n, n+1);
- X# endif
- X
- X n += 1;
- X
- X if ( (srcBytes -= n) < 0 ) goto ErrorExit;
- X if ( (dstBytes -= n) < 0 ) goto ErrorExit;
- X do { UPutByte(UGetByte()); } while (--n > 0);
- X }
- X
- X else if (n != 128) {
- X# ifdef DEBUG
- X fprintf (stderr, "Got %02x, repeating byte %d times...\n",
- X n, 257-n);
- X# endif
- X
- X n = 257 - n;
- X
- X if ( (srcBytes -= 1) < 0 ) goto ErrorExit;
- X if ( (dstBytes -= n) < 0 ) goto ErrorExit;
- X c = UGetByte();
- X do { UPutByte(c); } while (--n > 0);
- X }
- X }
- X error = FALSE; /* success! */
- X
- X ErrorExit:
- X *pSource = source; *pDest = dest;
- X
- X if (error)
- X { fprintf (stderr, "error in unpack, src %d, dst %d\n",
- X srcBytes, dstBytes);
- X }
- X
- X return(error);
- X }
- X
- X/****************************************************************
- X * read_iff: Read an Amiga format IFF Interleaved Bitmap
- X ****************************************************************/
- X
- Xread_iff (image, rfile, mstr, mlen)
- XFBM *image;
- XFILE *rfile;
- Xchar *mstr;
- Xint mlen;
- X{ char magic[8];
- X long formsize, buflen;
- X Chunk *form;
- X int result;
- X
- X /* First word is magic number */
- X magic[0] = NEXTMCH(rfile,mstr,mlen) & 0xff;
- X magic[1] = NEXTMCH(rfile,mstr,mlen) & 0xff;
- X magic[2] = NEXTMCH(rfile,mstr,mlen) & 0xff;
- X magic[3] = NEXTMCH(rfile,mstr,mlen) & 0xff;
- X magic[4] = '\0';
- X
- X /* If magic number is not FORM, lose */
- X if (strcmp (magic, "FORM") != 0)
- X { if (strncmp (magic, "FOR", 3) == 0 ||
- X strncmp (magic, "LIS", 3) == 0 ||
- X strncmp (magic, "CAT", 3) == 0)
- X { fprintf (stderr, "Sorry, I only handle FORM type IFF files\n");
- X return (0);
- X }
- X
- X fprintf (stderr,
- X "read_iff: error, file not a FORM type IFF file, magic '%s'\n",
- X magic);
- X return (0);
- X }
- X
- X /* Second longword is length of data chunk */
- X formsize = get_long (rfile, BIG);
- X
- X form = (Chunk *) malloc (formsize + 8);
- X form->ckID = FORM;
- X form->ckSize = formsize;
- X
- X /* Now read the rest of the chunk */
- X if ((buflen = fread (form->ckData, 1, formsize, stdin)) < formsize)
- X { if (buflen < 0)
- X { perror ("stdin"); }
- X else
- X { fprintf (stderr, "error: premature EOF in FORM after %d of %d bytes\n",
- X buflen, formsize);
- X }
- X
- X exit (1);
- X }
- X
- X /* Recursively parse the FORM */
- X result = parse_form (image, form);
- X
- X /* Now we've read the image (or not) */
- X free (form);
- X
- X return (result);
- X}
- X
- X/****************************************************************
- X * parse_form: Parse an IFF form chunk
- X *
- X * FORM ::= "FORM" #{ FormType (LocalChunk | FORM | LIST | CAT)* }
- X * FormType ::= ID
- X * LocalChunk ::= Property | Chunk
- X ****************************************************************/
- X
- Xparse_form (image, chunk)
- XFBM *image;
- XChunk *chunk;
- X{ register UBYTE *data, *tail;
- X register int clrlen, colors;
- X register BitMapHeader *bmh;
- X register int i, bits;
- X long formtype;
- X int found_bmhd=0, found_cmap=0, found_body=0;
- X Chunk *part;
- X
- X data = chunk->ckData;
- X tail = data + chunk->ckSize;
- X
- X formtype = MakeID(data[0], data[1], data[2], data[3]);
- X data += 4;
- X
- X if (formtype != ID_ILBM)
- X { fprintf (stderr, "this FORM doesn't start with ILBM, but %4.4s, sorry.\n",
- X &formtype);
- X return (0);
- X }
- X
- X while (data < tail)
- X { part = (Chunk *) data;
- X part->ckID = swapsize (part->ckID);
- X part->ckSize = swapsize (part->ckSize);
- X data += ( EVENALIGN (part->ckSize) + 8 );
- X
- X# ifdef DEBUG
- X fprintf (stderr, "Found %c%c%c%c, size %ld\n",
- X (part->ckID & 0xff000000) >> 24,
- X (part->ckID & 0x00ff0000) >> 16,
- X (part->ckID & 0x0000ff00) >> 8,
- X (part->ckID & 0x000000ff),
- X part->ckSize);
- X# endif
- X
- X if (part->ckID == ID_BMHD)
- X { found_bmhd++;
- X bmh = (BitMapHeader *) part->ckData;
- X
- X /* IFF uses BIG byte order, swap if necessary */
- X if (machine_byte_order () == LITTLE)
- X { bmh->w = swapword (bmh->w);
- X bmh->h = swapword (bmh->h);
- X bmh->x = swapword (bmh->x);
- X bmh->y = swapword (bmh->y);
- X bmh->transparentColor = swapword (bmh->transparentColor);
- X bmh->pageWidth = swapword (bmh->pageWidth);
- X bmh->pageHeight = swapword (bmh->pageHeight);
- X }
- X
- X image->hdr.rows = bmh->h;
- X image->hdr.cols = bmh->w;
- X image->hdr.planes = 1;
- X image->hdr.bits = bmh->nPlanes;
- X image->hdr.physbits = 8;
- X image->hdr.rowlen = 16 * ((image->hdr.cols + 15) / 16);
- X image->hdr.plnlen = image->hdr.rowlen * image->hdr.rows;
- X image->hdr.clrlen = 0;
- X image->hdr.aspect = (double) bmh->yAspect / bmh->xAspect;
- X image->hdr.title[0] = '\0';
- X image->hdr.credits[0] = '\0';
- X }
- X else if (part->ckID == ID_CMAP)
- X { image->hdr.clrlen = part->ckSize;
- X
- X alloc_fbm (image);
- X
- X clrlen = image->hdr.clrlen;
- X colors = clrlen / 3;
- X
- X for (i=0; i<image->hdr.clrlen; i++)
- X { image->cm[(colors * (i%3)) + i/3] = part->ckData[i]; }
- X
- X /* Compute number of bits in colormap */
- X for (i=colors, bits=1; i > 2; i /= 2, bits++) ;
- X
- X if (bits < image->hdr.bits) image->hdr.bits = bits;
- X
- X found_cmap++;
- X }
- X else if (part->ckID == ID_BODY)
- X { if (!found_bmhd)
- X { fprintf (stderr, "Error, BODY found with no BMHD header\n");
- X return (0);
- X }
- X
- X if (found_cmap == 0)
- X { alloc_fbm (image); }
- X
- X found_body++;
- X
- X /* Decode body */
- X fprintf (stderr, "Reading IFF [%dx%dx%d], %d physbits, %1.3lf aspect",
- X image->hdr.cols, image->hdr.rows,
- X image->hdr.bits, image->hdr.physbits,
- X image->hdr.aspect);
- X if (image->hdr.planes > 1)
- X { fprintf (stderr, ", %d planes", image->hdr.planes); }
- X if (image->hdr.clrlen > 1)
- X { fprintf (stderr, ", %d colors", image->hdr.clrlen / 3); }
- X if (bmh->compression)
- X { fprintf (stderr, ", compressed"); }
- X if (bmh->masking == mskHasMask)
- X { fprintf (stderr, ", with mask"); }
- X fprintf (stderr, "\n");
- X
- X# ifdef DEBUG
- X fprintf (stderr,
- X "masking %d, compression %d, transparent %d, page [%dx%d]\n",
- X bmh->masking, bmh->compression, bmh->transparentColor,
- X bmh->pageWidth, bmh->pageHeight);
- X
- X for (i=0; i<colors; i++)
- X { fprintf (stderr, " color %3d: <%3d, %3d, %3d>\n", i,
- X image->cm[i], image->cm[i+colors], image->cm[i+colors*2]);
- X }
- X# endif
- X
- X return (read_iff_body (image, bmh, part));
- X }
- X }
- X
- X return (0);
- X}
- X
- X/****************************************************************
- X * read_iff_body: Read the bits in the ILBM body into the FBM image
- X ****************************************************************/
- X
- Xread_iff_body (image, bmh, body)
- XFBM *image;
- XBitMapHeader *bmh;
- XChunk *body;
- X{ register int r, c, k, pmask, byte, bit;
- X unsigned char *row, *bp, *buf, *obm, *tail;
- X int bytlen = image->hdr.cols / 8;
- X int planes = bmh->nPlanes + ((bmh->masking == mskHasMask) ? 1 : 0);
- X
- X buf = (unsigned char *) malloc (bytlen);
- X
- X bp = body->ckData;
- X tail = bp + body->ckSize;
- X
- X# ifdef DEBUG
- X fprintf (stderr, "Body length %d, planes %d: ", tail-bp, planes);
- X for (c=0; c<20; c++) fprintf (stderr, "%02x", bp[c]);
- X fprintf (stderr, "\n");
- X# endif
- X
- X /* Each iteration reads one scan line */
- X for (r=0; r<image->hdr.rows; r++)
- X {
- X if (bp > tail)
- X { fprintf (stderr, "Ran out of data in body after %d of %d rows\n",
- X r, image->hdr.rows);
- X return (0);
- X }
- X
- X obm = &(image->bm[r * image->hdr.rowlen]);
- X
- X /* Clear the output row of pixels */
- X for (c=0; c<image->hdr.cols; c++)
- X { obm[c] = 0; }
- X
- X /* Each loop reads one plane of this scan line */
- X for (k=0; k<planes; k++)
- X {
- X /* First get pointer to data packed 8 bits per byte */
- X if (bmh->compression == 0)
- X { row = bp; bp += RowBytes (bmh->w); }
- X else
- X { row = buf;
- X if (UnPackRow (&bp, &row, (int) (tail-bp), RowBytes (bmh->w)) != 0)
- X { fprintf (stderr,
- X "%s, row %d of %d, plane %d of %d, bytes per row %d\n",
- X "Error in UnPackRow",
- X r, image->hdr.rows, k, planes, RowBytes (bmh->w));
- X return (0);
- X }
- X row = buf;
- X }
- X
- X /* Ignore extra planes (including the mask if any) */
- X if (k >= image->hdr.bits)
- X continue;
- X
- X /* Now OR in these bits into the output pixels */
- X pmask = 1 << k;
- X
- X for (c=0; c<image->hdr.cols; c++)
- X { byte = c >> 3;
- X bit = 7 - (c & 7);
- X bit = row[byte] & (1 << bit);
- X
- X obm[c] |= bit ? pmask : 0;
- X }
- X }
- X }
- X
- X if (tail-bp > 1)
- X { fprintf (stderr, "Warning, %d bytes of data unread\n", tail - bp); }
- X
- X return (1);
- X}
- X
- X/****************************************************************
- X * write_iff: Write AMIGA IFF format ILBM file
- X *
- X * Writes FORM type ILBM
- X * BMHD
- X * CMAP (optional)
- X * BODY (uncompressed)
- X *
- X ****************************************************************/
- X
- Xwrite_iff (image, wfile)
- XFBM *image;
- XFILE *wfile;
- X{ BitMapHeader bmhd;
- X unsigned char *cmap, *body;
- X int bodylen, cmaplen, bmhdlen, formlen, ilbmbits;
- X
- X if (image->hdr.planes > 1)
- X { fprintf (stderr, "Error, write_iff cannot handle multi-plane images\n");
- X return (0);
- X }
- X
- X /* Determine number of bits in output */
- X if (image->hdr.clrlen == 0)
- X { ilbmbits = image->hdr.bits; }
- X else
- X { int colors = image->hdr.clrlen/3;
- X for (ilbmbits=1; colors > 2; ilbmbits++, colors >>= 1) ;
- X }
- X
- X fprintf (stderr, "Writing \"%s\" [%dx%d] as a %d bit IFF ILBM file\n",
- X image->hdr.title[0] ? image->hdr.title : "",
- X image->hdr.cols, image->hdr.rows, ilbmbits);
- X
- X if (ilbmbits > 5)
- X { fprintf (stderr, "%s\n%s\n%s\n",
- X "Warning: most IFF ILBM displays cannot handle more than",
- X " 32 colors. You should probably run the image though",
- X " 'gray2clr -u | fbquant -c32' first.");
- X }
- X
- X /* Build BMHD, CMAP, and body chunks */
- X bmhdlen = build_bmhd (image, &bmhd, ilbmbits) ;
- X cmaplen = build_cmap (image, &cmap, ilbmbits);
- X bodylen = build_body (image, &body, ilbmbits);
- X
- X /* Length of FORM is length of subparts plus 8 for header + 4 for type */
- X formlen = bmhdlen + cmaplen + bodylen + 12;
- X
- X /*--------Write out FORM chunk header--------*/
- X fprintf (wfile, "FORM");
- X put_long (formlen-8, wfile, BIG);
- X fprintf (wfile, "ILBM");
- X
- X /*----Write out BMHD chunk----*/
- X fprintf (wfile, "BMHD");
- X put_long (bmhdlen-8, wfile, BIG);
- X fwrite (&bmhd, bmhdlen-8, 1, wfile);
- X
- X /* No need to pad BMHD chunk, it must be even */
- X
- X /*----Write out CMAP chunk----*/
- X if (cmaplen > 0)
- X { fprintf (wfile, "CMAP");
- X put_long (cmaplen-8, wfile, BIG);
- X fwrite (cmap, cmaplen-8, 1, wfile);
- X
- X /* Pad CMAP chunk if necessary */
- X if (cmaplen & 1) fputc (0, wfile);
- X }
- X
- X /*----Write out BODY chunk----*/
- X fprintf (wfile, "BODY");
- X put_long (bodylen-8, wfile, BIG);
- X fwrite (body, bodylen-8, 1, wfile);
- X
- X /* Pad BODY chunk if necessary */
- X if (bodylen & 1) fputc (0, wfile);
- X
- X /*--------Free memory and return--------*/
- X if (cmap) free (cmap);
- X if (body) free (body);
- X
- X return (1);
- X}
- X
- X/****************************************************************
- X * build_bmhd: Build a BitMapHeader, and byte swap it if necessary
- X ****************************************************************/
- X
- Xbuild_bmhd (image, bmh, bits)
- XFBM *image;
- XBitMapHeader *bmh;
- Xint bits;
- X{
- X bmh->w = image->hdr.cols;
- X bmh->h = image->hdr.rows;
- X bmh->x = 0;
- X bmh->y = 0;
- X bmh->nPlanes = bits;
- X bmh->masking = 0;
- X bmh->compression = 0;
- X bmh->pad1 = 0;
- X bmh->transparentColor = 0;
- X bmh->xAspect = 100;
- X bmh->yAspect = (image->hdr.aspect * 100.0) + 0.5;
- X bmh->pageWidth = bmh->w;
- X bmh->pageHeight = bmh->h;
- X
- X /* IFF uses BIG byte order, swap if necessary */
- X if (machine_byte_order () == LITTLE)
- X { bmh->w = swapword (bmh->w);
- X bmh->h = swapword (bmh->h);
- X bmh->x = swapword (bmh->x);
- X bmh->y = swapword (bmh->y);
- X bmh->transparentColor = swapword (bmh->transparentColor);
- X bmh->pageWidth = swapword (bmh->pageWidth);
- X bmh->pageHeight = swapword (bmh->pageHeight);
- X }
- X
- X return (sizeof (*bmh) + 8);
- X}
- X
- X/****************************************************************
- X * build_cmap: Convert an FBM format colormap to IFF format
- X ****************************************************************/
- X
- Xbuild_cmap (image, cmap, bits)
- XFBM *image;
- Xunsigned char **cmap;
- Xint bits;
- X{ register int len, i;
- X register unsigned char *r, *g, *b, *c;
- X int colors;
- X
- X colors = image->hdr.clrlen / 3;
- X
- X r = image->cm;
- X g = r + colors;
- X b = g + colors;
- X
- X len = 3*colors;
- X *cmap = (unsigned char *) malloc (len);
- X
- X /* Now convert from three vectors to a vector of triples */
- X for (i=0, c= *cmap; i<colors; i++)
- X { *c++ = *r++;
- X *c++ = *g++;
- X *c++ = *b++;
- X }
- X
- X /* Return length of chunk, just length of map plus 8 bytes chunk header */
- X return (len + 8);
- X}
- X
- X/****************************************************************
- X * build_body: Interleave the bits for the byte plane
- X ****************************************************************/
- X
- Xbuild_body (image, body, bits)
- Xregister FBM *image;
- Xunsigned char **body;
- Xint bits;
- X{ int bpr, size;
- X register unsigned char *obm, *bmp;
- X register int r, c, k, mask, byte, bit;
- X
- X bpr = RowBytes (image->hdr.cols);
- X
- X size = bpr * image->hdr.rows * bits;
- X
- X *body = (unsigned char *) malloc (size);
- X
- X obm = *body;
- X
- X for (r=0; r < image->hdr.rows; r++)
- X { for (k=0; k<bits; k++)
- X { mask = 1 << k;
- X bmp = &(image->bm[r * image->hdr.rowlen]);
- X
- X# ifdef DEBUG
- X if (r==23)
- X { fprintf (stderr, "Row %d, plane %d, bytes: ", r, k);
- X for (c=0; c<32; c++) fprintf (stderr, "%02x", bmp[c]);
- X fprintf (stderr, "\n");
- X }
- X# endif
- X
- X for (c=0, byte=0; c<image->hdr.cols; c++)
- X { bit = (*bmp++ & mask) ? 1 : 0;
- X
- X
- X# ifdef DEBUG
- X if (r == 23 && c < 32)
- X { fprintf (stderr, "%d", bit); }
- X# endif
- X
- X byte = (byte << 1) | bit;
- X if ((c&7) == 7)
- X { *obm++ = byte;
- X
- X# ifdef DEBUG
- X if (r == 23 && c <32) fprintf (stderr, " %d ", byte);
- X# endif
- X
- X byte=0;
- X }
- X }
- X
- X# ifdef DEBUG
- X if (r == 23) fprintf (stderr, "\n");
- X# endif
- X
- X if ((c & 7) != 0)
- X { while ((c&7) != 0)
- X { c++; byte <<= 1; }
- X *obm++ = byte;
- X }
- X }
- X }
- X
- X return (size + 8);
- X
- X}
- END_OF_FILE
- if test 23454 -ne `wc -c <'fliff.c'`; then
- echo shar: \"'fliff.c'\" unpacked with wrong size!
- fi
- # end of 'fliff.c'
- fi
- echo shar: End of archive 7 \(of 8\).
- cp /dev/null ark7isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 8 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-